#include "BlockingQueue.hpp"
#include "Thread.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include "Task.hpp"
#include <ctime>

using namespace ThreadModule;

using bolckqueue_t = BlockQueue<Task>;

class ThreadData
{
public:
    ThreadData(bolckqueue_t &bq, const std::string &who = "none-name") : _bq(bq), _who(who)
    {}

    std::string GetThreadname()
    {
        return _who;
    }

    bolckqueue_t& Excutebq()
    {
        return _bq;
    }
private:
    bolckqueue_t &_bq;
    std::string _who;
};

void Productor(ThreadData &data)
{
    // int cnt = 1;
    srand(time(nullptr) ^ pthread_self());
    while (true)
    {
        sleep(1);
        // 1. 获取任务
        int a = rand() % 10 + 1;
        usleep(1234);
        int b = rand() % 10 + 1;
        Task t(a, b);
        // 2. 把获取的任务，放入blockqueue
        data.Excutebq().Enqueue(t);
        std::cout << data.GetThreadname() << ",Productor prodect data is:" << t.DebugtTostring() << std::endl;
        // cnt++;
    }
}

void Consumer(ThreadData &data)
{
    while (true)
    {
        // sleep(1);
        // int data;
        // 1. 从blockqueue中拿到任务
        Task t;
        data.Excutebq().Pop(&t);
        // 2. 处理任务
        t.Excute();
        std::cout << data.GetThreadname() << ",Consumer consume data:" << t.ResultTostring() << std::endl;
    }
}

void StartComm(std::vector<Thread<ThreadData>> *threads, int num, bolckqueue_t &bq, func_t<ThreadData> func)
{
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        // data.SetThreadname(name);
        ThreadData* data = new ThreadData(bq, name);
        threads->emplace_back(func, *data, name);//同样的问题，不能要传data指针过去，data指针是个局变量
        threads->back().Start();
    }
}

void StartProductor(std::vector<Thread<ThreadData>> *threads, int num, bolckqueue_t &bq)
{
    StartComm(threads, num, bq, Productor);
}

void StartConsumer(std::vector<Thread<ThreadData>> *threads, int num, bolckqueue_t &bq)
{
    StartComm(threads, num, bq, Consumer);
}

void WaitAlltrhead(std::vector<Thread<ThreadData>> &threads, std::vector<ThreadData *> &Data)
{
    for (auto &thread : threads)
    {
        thread.Join();
    }
    for (auto &data : Data)
    {
        delete data;
    }
}

int main()
{
    // 阻塞队列
    bolckqueue_t *bq = new bolckqueue_t(5);
    // ThreadData* data = new ThreadData(*bq);
    std::vector<Thread<ThreadData>> threads;
    std::vector<ThreadData *> Data;
    StartProductor(&threads, 2, *bq);
    StartConsumer(&threads, 5, *bq);
    WaitAlltrhead(threads, Data);
    return 0;
}

// using namespace ThreadModule;

// using bolckqueue_t = BlockQueue<Task>;

// void Productor(bolckqueue_t &bq)
// {
//     // int cnt = 1;
//     srand(time(nullptr) ^ pthread_self());
//     while (true)
//     {
//         sleep(1);
//         // 1. 获取任务
//         int a = rand() % 10 + 1;
//         usleep(1234);
//         int b = rand() % 10 + 1;
//         Task t(a, b);
//         // 2. 把获取的任务，放入blockqueue
//         bq.Enqueue(t);
//         std::cout << "Productor prodect data is:" << t.DebugtTostring() << std::endl;
//         // cnt++;
//     }
// }

// void Consumer(bolckqueue_t &bq)
// {
//     while (true)
//     {
//         // sleep(1);
//         // int data;
//         // 1. 从blockqueue中拿到任务
//         Task t;
//         bq.Pop(&t);
//         // 2. 处理任务
//         t.Excute();
//         std::cout << "Consumer consume data:" << t.ResultTostring() << std::endl;
//     }
// }

// void StartComm(std::vector<Thread<bolckqueue_t>> *threads, int num, bolckqueue_t &bq, func_t<bolckqueue_t> func)
// {
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         threads->emplace_back(func, bq, name);
//         threads->back().Start();
//     }
// }

// void StartProductor(std::vector<Thread<bolckqueue_t>> *threads, int num, bolckqueue_t &bq)
// {
//     StartComm(threads, num, bq, Productor);
// }

// void StartConsumer(std::vector<Thread<bolckqueue_t>> *threads, int num, bolckqueue_t &bq)
// {
//     StartComm(threads, num, bq, Consumer);
// }

// void WaitAlltrhead(std::vector<Thread<bolckqueue_t>> &threads)
// {
//     for (auto &thread : threads)
//     {
//         thread.Join();
//     }
// }

// int main()
// {
//     // 阻塞队列
//     bolckqueue_t *bq = new bolckqueue_t(5);
//     std::vector<Thread<bolckqueue_t>> threads;

//     StartProductor(&threads, 1, *bq);
//     StartConsumer(&threads, 3, *bq);
//     WaitAlltrhead(threads);
//     return 0;
// }

// using namespace ThreadModule;

// void Productor(BlockQueue<int>* &bq)
// {
//     // int cnt = 1;
//     while (true)
//     {
//         bq->Enqueue(1);
//         std::cout << "Productor prodect data:" << std::endl;
//         // cnt++;
//         sleep(1);
//     }
// }

// void Consumer(BlockQueue<int>* &bq)
// {
//     while (true)
//     {
//         int data;
//         bq->Pop(&data);
//         std::cout << "Consumer consume data:"<< data << std::endl;
//     }
// }

// void StartComm(std::vector<Thread<BlockQueue<int>*>> *threads, int num, BlockQueue<int>* bq, func_t<BlockQueue<int>*> func)
// {
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         threads->emplace_back(Productor, bq, name);
//         threads->back().Start();
//     }
// }

// void StartProductor(std::vector<Thread<BlockQueue<int>*>> *threads, int num, BlockQueue<int>* bq)
// {
//     StartComm(threads, num, bq, Productor);
// }

// void StartConsumer(std::vector<Thread<BlockQueue<int>*>> *threads, int num, BlockQueue<int>* bq)
// {
//     StartComm(threads, num, bq, Consumer);
// }

// void WaitAlltrhead(std::vector<Thread<BlockQueue<int>*>> &threads)
// {
//     for (auto &thread : threads)
//     {
//         thread.Join();
//     }
// }

// int main()
// {
//     //阻塞队列
//     BlockQueue<int>* bq = new BlockQueue<int>(5);//坑点，Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,v
//     std::vector<Thread<BlockQueue<int>*>> threads;

//     StartProductor(&threads, 1, bq);//这里bq是值传递Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,Bug,
//     StartConsumer(&threads, 1, bq);
//     WaitAlltrhead(threads);
//     return 0;
// }